<script setup lang="ts">
import type { JobStatus } from '@shared/types/'
import { Delete, Refresh } from '@element-plus/icons-vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { storeToRefs } from 'pinia'
import { computed, onMounted, onUnmounted, ref, watch } from 'vue'
import { useAppStore } from '../stores/app'

const appStore = useAppStore()
const currentPage = ref(1)
const pageSize = ref(20)

// 计算属性
const { jobs, runningJobs } = storeToRefs(appStore)

// 筛选与搜索
const filterStatus = ref('')
const filterKeyword = ref('')

const filteredJobs = computed(() => {
  const kw = (filterKeyword.value || '').trim().toLowerCase()
  const st = (filterStatus.value || '').trim().toLowerCase()
  return jobs.value.filter((row: any) => {
    if (st && String(row.status || '').toLowerCase() !== st)
      return false
    if (!kw)
      return true
    const r = (row as any) || {}
    const res = (r.result || {}) as any
    const ai = (res.appointment_info || {}) as any
    const hay = [
      r.job_id,
      res.reference_number,
      res.selected_date,
      res.selected_timeslot,
      ai.user_passport,
      ai.user_name,
      ai.user_email,
      ai.appointment_date,
      ai.appointment_time,
      ai.office_code,
    ]
      .filter(Boolean)
      .map((v: any) => String(v).toLowerCase())
      .join(' ')
    return hay.includes(kw)
  })
})

const paginatedJobs = computed(() => {
  const start = (currentPage.value - 1) * pageSize.value
  const end = start + pageSize.value
  return filteredJobs.value.slice(start, end)
})

// 方法
function getStatusClass(status: string) {
  switch (status) {
    case 'running': return 'info'
    case 'success': return 'success'
    case 'failed': return 'danger'
    case 'cancelled': return 'warning'
    default: return 'info'
  }
}

function getProgressStatus(status: string) {
  switch (status) {
    case 'success': return 'success'
    case 'failed': return 'exception'
    default: return undefined
  }
}

function getTagType(status: string) {
  switch (status) {
    case 'running': return 'primary'
    case 'success': return 'success'
    case 'failed': return 'danger'
    case 'cancelled': return 'warning'
    case 'pending': return 'info'
    default: return ''
  }
}

function getStatusText(status: string) {
  const statusMap: Record<string, string> = {
    pending: '等待中',
    running: '运行中',
    success: '成功',
    failed: '失败',
    cancelled: '已取消',
  }
  return statusMap[status] || status
}

function formatTime(timestamp?: number) {
  if (!timestamp)
    return '-'
  return new Date(timestamp * 1000).toLocaleString('zh-CN')
}

function formatDuration(startTime?: number) {
  if (!startTime)
    return '-'
  const duration = Date.now() - (startTime * 1000)
  const seconds = Math.floor(duration / 1000)
  const minutes = Math.floor(seconds / 60)
  const hours = Math.floor(minutes / 60)

  if (hours > 0) {
    return `${hours}时${minutes % 60}分${seconds % 60}秒`
  }
  else if (minutes > 0) {
    return `${minutes}分${seconds % 60}秒`
  }
  else {
    return `${seconds}秒`
  }
}

function formatJobDuration(job: JobStatus) {
  if (!job.start_time)
    return '-'

  const endTime = job.end_time || (Date.now() / 1000)
  const duration = (endTime - job.start_time) * 1000

  if (duration < 60000) {
    return `${Math.floor(duration / 1000)}秒`
  }
  else if (duration < 3600000) {
    return `${Math.floor(duration / 60000)}分钟`
  }
  else {
    return `${Math.floor(duration / 3600000)}小时`
  }
}

async function refreshJobs() {
  try {
    await appStore.loadJobs()
    ElMessage.success('任务列表已刷新')
  }
  catch (error) {
    console.error('刷新任务列表失败:', error)
    ElMessage.error('刷新失败')
  }
}

function exportJobsCsv() {
  try {
    const cols = [
      'JobID',
      '类型',
      '状态',
      '进度',
      '开始时间',
      '结束时间',
      '参考编号',
      '预约日期',
      '预约时间',
      '地点',
      '护照号',
      '姓名',
      '总上行(B)',
      '总下行(B)',
      '总流量(B)',
      '错误信息',
    ]
    const rows = filteredJobs.value.map((row: any) => {
      const res = (row?.result || {}) as any
      const ai = (res.appointment_info || {}) as any
      const up = Number(res?.traffic?.totalUp || 0)
      const down = Number(res?.traffic?.totalDown || 0)
      const total = up + down
      const fmtTs = (s?: number) => (typeof s === 'number' ? new Date(s * 1000).toLocaleString('zh-CN', { hour12: false }).replace(/\//g, '-') : '')
      return [
        row.job_id,
        row.type || '',
        row.status || '',
        row.progress ?? '',
        fmtTs(row.start_time),
        fmtTs(row.end_time),
        res.reference_number || '',
        ai.appointment_date || res.selected_date || '',
        ai.appointment_time || res.selected_timeslot || '',
        ai.office_code || '',
        ai.user_passport || '',
        ai.user_name || '',
        up,
        down,
        total,
        row.error || '',
      ]
    })
    const csv = [cols, ...rows]
      .map(r => r.map(c => `"${String(c).replace(/"/g, '""')}"`).join(','))
      .join('\n')
    const blob = new Blob([`\uFEFF${csv}`], { type: 'text/csv;charset=utf-8;' })
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = `jobs_${new Date().toISOString().slice(0, 19).replace(/[-:T]/g, '')}.csv`
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
    URL.revokeObjectURL(url)
    ElMessage.success('CSV 已导出')
  }
  catch (e) {
    console.error('导出失败', e)
    ElMessage.error('导出失败')
  }
}

async function clearHistory() {
  try {
    await ElMessageBox.confirm('确定要清空所有历史记录吗？运行中的任务将被保留。', '确认清空', {
      type: 'warning',
    })

    const deleted = await appStore.clearHistory({ keep_running: true })
    ElMessage.success(`已清空历史，共删除 ${deleted} 条记录`)
  }
  catch {
    // 用户取消
  }
}

async function stopJob(job: any) {
  try {
    if (job?.type === 'monitor') {
      await window.api.booking.monitorStop()
    }
    else if (job?.type && String(job.type).startsWith('booking')) {
      await window.api.booking.stop()
    }
    else {
      await appStore.stopScript(job?.job_id)
    }
    ElMessage.success('任务已停止')
    await appStore.loadJobs()
  }
  catch (error) {
    console.error('停止任务失败:', error)
    ElMessage.error('停止任务失败')
  }
}

// 详情弹窗状态（先声明，避免使用前未定义）
const detailVisible = ref(false)
const detailJob = ref<JobStatus | null>(null)

function viewJobDetail(job: JobStatus) {
  detailJob.value = job
  detailVisible.value = true
}
const logKeyword = ref('')
const logPhase = ref<'all' | 'start' | 'info' | 'warn' | 'success' | 'error'>('all')

function getPhaseTagType(phase?: string) {
  switch (phase) {
    case 'success': return 'success'
    case 'warn': return 'warning'
    case 'error': return 'danger'
    case 'start': return 'info'
    default: return 'info'
  }
}

const detailResult = computed(() => (detailJob.value?.result || {}) as any)
// 关键：当任务列表刷新时，若详情弹窗打开，使用最新的同ID任务对象以带来 result.releases 等动态更新
watch(() => jobs.value, (list) => {
  try {
    if (!detailVisible.value || !detailJob.value)
      return
    const id = detailJob.value.job_id
    const updated = (list || []).find((j: any) => j && j.job_id === id)
    if (updated && updated !== detailJob.value)
      detailJob.value = updated as any
  }
  catch {}
})
const isBatchJob = computed(() => {
  const t = (detailJob.value as any)?.type
  if (t && String(t).toLowerCase() === 'booking_batch')
    return true
  return Array.isArray((detailResult.value as any)?.appointments)
})
const batchRows = computed(() => {
  if (!isBatchJob.value)
    return [] as Array<any>
  const res = detailResult.value || {}
  const list: Array<any> = Array.isArray(res.appointments) ? res.appointments : []
  const results: Array<any> = Array.isArray(res.results) ? res.results : []
  const byId = new Map<number, any>()
  for (const r of results) byId.set(Number(r?.id), r)
  return list.map((a: any) => {
    const r = byId.get(Number(a?.id)) || {}
    return {
      id: a?.id,
      user_passport: a?.user_passport || '',
      user_name: a?.user_name || '',
      office_code: a?.office_code || '',
      success: !!r?.success,
      error: r?.error || '',
      reference_number: r?.reference_number || '',
      selected_date: r?.selected_date || '',
      selected_timeslot: r?.selected_timeslot || '',
    }
  })
})
const detailLogs = computed(() => {
  const logs = Array.isArray((detailResult.value as any)?.logs) ? (detailResult.value as any).logs : []
  return logs as Array<{ timestamp: number, step?: string, phase?: string, message?: string }>
})

const filteredLogs = computed(() => {
  const kw = (logKeyword.value || '').trim().toLowerCase()
  const ph = logPhase.value
  return detailLogs.value.filter((l) => {
    if (ph !== 'all' && String(l.phase || '').toLowerCase() !== ph)
      return false
    if (!kw)
      return true
    const hay = `${l.step || ''} ${l.message || ''}`.toLowerCase()
    return hay.includes(kw)
  })
})

const trafficRows = computed(() => {
  const traffic = (detailResult.value as any)?.traffic
  const per = traffic?.perStep || {}
  const rows: Array<{ step: string, up: number, down: number, count: number }> = []
  for (const k of Object.keys(per)) {
    rows.push({ step: k, up: Number(per[k]?.up || 0), down: Number(per[k]?.down || 0), count: Number(per[k]?.count || 0) })
  }
  return rows
})

async function copyLogs() {
  try {
    const lines = filteredLogs.value.map(l => `${new Date((l.timestamp || 0) * 1000).toLocaleString('zh-CN')} [${l.phase || ''}] ${l.step || ''} ${l.message || ''}`)
    await navigator.clipboard.writeText(lines.join('\n'))
    ElMessage.success('日志已复制到剪贴板')
  }
  catch (e) {
    console.error('复制失败', e)
    ElMessage.error('复制失败')
  }
}

function exportLogs(format: 'json' | 'txt' = 'json') {
  try {
    const job = detailJob.value
    if (!job)
      return
    const payload: any = {
      job_id: job.job_id,
      status: job.status,
      progress: job.progress ?? null,
      current_step: job.current_step ?? null,
      start_time: job.start_time ?? null,
      end_time: job.end_time ?? null,
      result: detailResult.value || {},
      logs: filteredLogs.value,
    }
    const content = format === 'json'
      ? JSON.stringify(payload, null, 2)
      : filteredLogs.value.map(l => `${new Date((l.timestamp || 0) * 1000).toLocaleString('zh-CN')} [${l.phase || ''}] ${l.step || ''} ${l.message || ''}`).join('\n')
    const blob = new Blob([content], { type: format === 'json' ? 'application/json' : 'text/plain' })
    const url = URL.createObjectURL(blob)
    const a = document.createElement('a')
    a.href = url
    a.download = `job_${job.job_id}.${format === 'json' ? 'logs.json' : 'logs.txt'}`
    document.body.appendChild(a)
    a.click()
    document.body.removeChild(a)
    URL.revokeObjectURL(url)
  }
  catch (e) {
    console.error('导出失败', e)
    ElMessage.error('导出失败')
  }
}

function formatBytes(n?: number): string {
  const v = Number(n || 0)
  if (v < 1024)
    return `${v} B`
  const kb = v / 1024
  if (kb < 1024)
    return `${kb.toFixed(2)} KB`
  const mb = kb / 1024
  if (mb < 1024)
    return `${mb.toFixed(2)} MB`
  const gb = mb / 1024
  return `${gb.toFixed(2)} GB`
}

// 定时刷新
let refreshTimer: ReturnType<typeof setInterval> | null = null

onMounted(async () => {
  await appStore.loadJobs()

  // 每5秒刷新一次任务状态
  refreshTimer = setInterval(() => {
    appStore.loadJobs()
  }, 5000)
})

onUnmounted(() => {
  if (refreshTimer) {
    clearInterval(refreshTimer)
  }
})
</script>

<template>
  <div class="monitor-page">
    <div class="mb-6">
      <h2 class="mb-2 text-2xl text-gray-800 font-bold">
        监控面板
      </h2>
      <p class="text-gray-600">
        实时监控任务状态和系统性能
      </p>
    </div>

    <!-- 实时状态 -->
    <div class="grid grid-cols-1 mb-6 gap-6">
      <!-- 任务状态 -->
      <div class="card">
        <h3 class="mb-4 text-lg font-semibold">
          任务状态
        </h3>

        <div v-if="runningJobs.length === 0" class="empty-container">
          <div class="empty-icon">
            ⏸️
          </div>
          <div class="empty-text">
            暂无运行中的任务
          </div>
          <div class="empty-description">
            所有任务已完成或暂停
          </div>
        </div>

        <div v-else>
          <div v-for="job in runningJobs" :key="job.job_id" class="mb-4 last:mb-0">
            <div class="mb-2 flex items-center justify-between">
              <div class="flex items-center">
                <span class="status-dot" :class="getStatusClass(job.status)" />
                <span class="font-medium">{{ job.current_step || '执行中' }}</span>
              </div>
              <span class="text-sm text-gray-500">{{ job.progress || 0 }}%</span>
            </div>

            <el-progress
              :percentage="job.progress || 0"
              :status="getProgressStatus(job.status)"
              class="mb-2"
            />

            <div class="flex items-center justify-between text-sm text-gray-500">
              <span>ID: {{ job.job_id.slice(0, 8) }}...</span>
              <span>{{ formatDuration(job.start_time) }}</span>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 任务历史 -->
    <div class="card">
      <div class="mb-4 flex items-center justify-between">
        <h3 class="text-lg font-semibold">
          任务历史
        </h3>
        <div class="flex items-center space-x-2">
          <el-select v-model="filterStatus" size="small" placeholder="状态" style="width: 120px;">
            <el-option label="全部" value="" />
            <el-option label="等待中" value="pending" />
            <el-option label="运行中" value="running" />
            <el-option label="成功" value="success" />
            <el-option label="失败" value="failed" />
            <el-option label="已取消" value="cancelled" />
          </el-select>
          <el-input v-model="filterKeyword" size="small" placeholder="搜索(护照/姓名/时间/地点/参考号)" style="width: 260px;" clearable />
          <el-button size="small" @click="refreshJobs">
            <el-icon><Refresh /></el-icon>
            刷新
          </el-button>
          <el-button size="small" @click="exportJobsCsv">
            导出 CSV
          </el-button>
          <el-button size="small" @click="clearHistory">
            <el-icon><Delete /></el-icon>
            清空历史
          </el-button>
        </div>
      </div>

      <el-table
        :data="paginatedJobs"
        stripe
        class="w-full"
        empty-text="暂无任务记录"
      >
        <el-table-column label="任务ID" width="120">
          <template #default="{ row }">
            <code class="text-sm">{{ row.job_id.slice(0, 8) }}...</code>
          </template>
        </el-table-column>

        <el-table-column label="状态" width="100">
          <template #default="{ row }">
            <el-tag
              :type="getTagType(row.status)"
              size="small"
            >
              {{ getStatusText(row.status) }}
            </el-tag>
          </template>
        </el-table-column>

        <el-table-column label="进度" width="100">
          <template #default="{ row }">
            <span>{{ row.progress || 0 }}%</span>
          </template>
        </el-table-column>

        <el-table-column label="当前步骤" min-width="150">
          <template #default="{ row }">
            {{ row.current_step || '-' }}
          </template>
        </el-table-column>

        <el-table-column label="开始时间" width="160">
          <template #default="{ row }">
            {{ formatTime(row.start_time) }}
          </template>
        </el-table-column>

        <el-table-column label="耗时" width="100">
          <template #default="{ row }">
            {{ formatJobDuration(row) }}
          </template>
        </el-table-column>

        <el-table-column label="总流量(计费)" width="140">
          <template #default="{ row }">
            {{ formatBytes(((row as any)?.result?.traffic?.totalUp || 0)
              + ((row as any)?.result?.traffic?.totalDown || 0)) }}
          </template>
        </el-table-column>

        <el-table-column label="预约信息" min-width="180">
          <template #default="{ row }">
            <div v-if="Array.isArray((row as any)?.result?.appointments)">
              批次：成功 {{ (row as any)?.result?.success || 0 }}/{{ (row as any)?.result?.total || 0 }}
            </div>
            <div v-else-if="(row as any)?.result?.appointment_info">
              <div class="font-medium">
                {{ (row as any).result.appointment_info.appointment_date || '-' }}
              </div>
              <div class="text-sm text-gray-500">
                {{ (row as any).result.appointment_info.appointment_time || '-' }}
              </div>
              <div class="text-sm text-gray-500">
                {{ (row as any).result.appointment_info.office_code || '-' }}
              </div>
            </div>
            <span v-else class="text-gray-400">-</span>
          </template>
        </el-table-column>

        <el-table-column label="操作" width="120" fixed="right">
          <template #default="{ row }">
            <div class="flex space-x-1">
              <el-button
                v-if="row.status === 'running'"
                size="small"
                type="danger"
                @click="stopJob(row)"
              >
                停止
              </el-button>
              <el-tag v-else-if="row.type === 'monitor' && row.status !== 'running'" size="small" type="info">
                已停止
              </el-tag>
              <el-button
                size="small"
                @click="viewJobDetail(row)"
              >
                详情
              </el-button>
            </div>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页 -->
      <div class="mt-4 flex justify-center">
        <el-pagination
          v-model:current-page="currentPage"
          v-model:page-size="pageSize"
          :total="filteredJobs.length"
          :page-sizes="[10, 20, 50, 100]"
          layout="total, sizes, prev, pager, next, jumper"
          small
        />
      </div>
    </div>
  </div>

  <!-- 详情弹窗（表单/分区布局） -->
  <el-dialog
    v-model="detailVisible"
    title="任务详情"
    width="800px"
  >
    <div class="space-y-4">
      <el-descriptions :column="2" border>
        <el-descriptions-item label="任务ID">
          <code>{{ detailJob?.job_id }}</code>
        </el-descriptions-item>
        <el-descriptions-item label="状态">
          <el-tag :type="getTagType(detailJob?.status || 'pending')">
            {{ getStatusText(detailJob?.status || 'pending') }}
          </el-tag>
        </el-descriptions-item>
        <el-descriptions-item label="进度">
          {{ `${detailJob?.progress ?? 0}%` }}
        </el-descriptions-item>
        <el-descriptions-item label="当前步骤">
          {{ detailJob?.current_step || '-' }}
        </el-descriptions-item>
        <el-descriptions-item label="开始时间">
          {{ formatTime(detailJob?.start_time) }}
        </el-descriptions-item>
        <el-descriptions-item label="结束时间">
          {{ formatTime(detailJob?.end_time) }}
        </el-descriptions-item>
      </el-descriptions>

      <el-descriptions :column="2" border>
        <el-descriptions-item label="参考编号">
          {{ (detailResult as any)?.reference_number || '-' }}
        </el-descriptions-item>
        <el-descriptions-item label="选择日期">
          {{ (detailResult as any)?.selected_date || '-' }}
        </el-descriptions-item>
        <el-descriptions-item label="选择时段">
          {{ (detailResult as any)?.selected_timeslot || '-' }}
        </el-descriptions-item>
        <el-descriptions-item label="错误信息">
          {{ detailJob?.error || '-' }}
        </el-descriptions-item>
      </el-descriptions>

      <el-descriptions v-if="Array.isArray((detailResult as any)?.releases) && (detailResult as any).releases.length" :column="1" border class="mt-3">
        <el-descriptions-item label="放号记录">
          <el-table :data="(detailResult as any).releases" size="small" border>
            <el-table-column label="时间" width="180">
              <template #default="{ row }">
                {{ new Date((row.timestamp || 0) * 1000).toLocaleString('zh-CN') }}
              </template>
            </el-table-column>
            <el-table-column label="放号日期">
              <template #default="{ row }">
                {{ (row.dates || []).join(', ') }}
              </template>
            </el-table-column>
            <el-table-column label="允许范围" width="220">
              <template #default="{ row }">
                <span v-if="row.allowed && (row.allowed.start || row.allowed.end)">
                  {{ row.allowed.start || '' }} ~ {{ row.allowed.end || '' }}
                </span>
                <span v-else>-</span>
              </template>
            </el-table-column>
            <el-table-column label="原因" prop="reason" width="140" />
          </el-table>
        </el-descriptions-item>
      </el-descriptions>

      <div class="card p-3">
        <h4 class="mb-2 text-base font-semibold">
          流量消耗
        </h4>
        <div class="mb-2 text-sm text-gray-600">
          单位：字节（Byte）
        </div>
        <el-descriptions :column="2" border>
          <el-descriptions-item label="总上行">
            {{ formatBytes((detailResult as any)?.traffic?.totalUp) }}
          </el-descriptions-item>
          <el-descriptions-item label="总下行">
            {{ formatBytes((detailResult as any)?.traffic?.totalDown) }}
          </el-descriptions-item>
        </el-descriptions>
        <div class="mt-3">
          <el-table :data="trafficRows" size="small" border>
            <el-table-column label="步骤" prop="step" />
            <el-table-column label="上行" width="160">
              <template #default="{ row }">
                {{ formatBytes(row.up) }}
              </template>
            </el-table-column>
            <el-table-column label="下行" width="160">
              <template #default="{ row }">
                {{ formatBytes(row.down) }}
              </template>
            </el-table-column>
            <el-table-column label="请求数" prop="count" width="100" />
          </el-table>
        </div>
      </div>

      <el-descriptions v-if="(detailResult as any)?.appointment_info" :column="2" border class="mt-3">
        <el-descriptions-item label="护照号码">
          {{ (detailResult as any).appointment_info.user_passport || '-' }}
        </el-descriptions-item>
        <el-descriptions-item label="驾照号码">
          {{ (detailResult as any).appointment_info.user_license || '-' }}
        </el-descriptions-item>
        <el-descriptions-item label="姓名">
          {{ (detailResult as any).appointment_info.user_name || '-' }}
        </el-descriptions-item>
        <el-descriptions-item label="邮箱">
          {{ (detailResult as any).appointment_info.user_email || '-' }}
        </el-descriptions-item>
        <el-descriptions-item label="电话">
          {{ (detailResult as any).appointment_info.user_phone || '-' }}
        </el-descriptions-item>
        <el-descriptions-item label="服务/地点">
          {{ (detailResult as any).appointment_info.service_type || '-' }} / {{ (detailResult as any).appointment_info.office_code || '-' }}
        </el-descriptions-item>
        <el-descriptions-item label="预约日期">
          {{ (detailResult as any).appointment_info.appointment_date || '-' }}
        </el-descriptions-item>
        <el-descriptions-item label="预约时间">
          {{ (detailResult as any).appointment_info.appointment_time || '-' }}
        </el-descriptions-item>
      </el-descriptions>

      <div v-if="isBatchJob" class="card mt-3 p-3">
        <h4 class="mb-2 text-base font-semibold">
          预约清单
        </h4>
        <div class="mb-2 text-sm text-gray-600">
          合计：{{ (detailResult as any)?.total || batchRows.length }}；成功：{{ (detailResult as any)?.success || batchRows.filter(r => r.success).length }}；失败：{{ (detailResult as any)?.failed || batchRows.filter(r => !r.success).length }}
        </div>
        <el-table :data="batchRows" size="small" border>
          <el-table-column label="ID" prop="id" width="80" />
          <el-table-column label="护照" prop="user_passport" width="140" />
          <el-table-column label="姓名" prop="user_name" width="120" />
          <el-table-column label="地点" prop="office_code" width="120" />
          <el-table-column label="结果" width="100">
            <template #default="{ row }">
              <el-tag :type="row.success ? 'success' : 'danger'">
                {{ row.success ? '成功' : '失败' }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column label="参考号" prop="reference_number" width="160" />
          <el-table-column label="日期" prop="selected_date" width="140" />
          <el-table-column label="时间" prop="selected_timeslot" width="140" />
          <el-table-column label="错误" prop="error" />
        </el-table>
      </div>

      <div>
        <div class="mb-2 flex items-center justify-between">
          <div class="flex items-center space-x-2">
            <el-input v-model="logKeyword" size="small" placeholder="搜索日志关键词（步骤/内容）" style="width: 260px;" />
            <el-select v-model="logPhase" size="small" style="width: 140px;">
              <el-option label="全部" value="all" />
              <el-option label="开始" value="start" />
              <el-option label="信息" value="info" />
              <el-option label="警告" value="warn" />
              <el-option label="成功" value="success" />
              <el-option label="错误" value="error" />
            </el-select>
          </div>
          <div class="flex items-center space-x-2">
            <el-button size="small" @click="copyLogs">
              复制日志
            </el-button>
            <el-dropdown>
              <el-button size="small">
                导出
              </el-button>
              <template #dropdown>
                <el-dropdown-menu>
                  <el-dropdown-item @click="exportLogs('json')">
                    导出 JSON
                  </el-dropdown-item>
                  <el-dropdown-item @click="exportLogs('txt')">
                    导出 TXT
                  </el-dropdown-item>
                </el-dropdown-menu>
              </template>
            </el-dropdown>
          </div>
        </div>

        <el-table :data="filteredLogs" height="300" size="small" border>
          <el-table-column label="时间" width="160">
            <template #default="{ row }">
              {{ new Date((row.timestamp || 0) * 1000).toLocaleString('zh-CN') }}
            </template>
          </el-table-column>
          <el-table-column label="级别" width="100">
            <template #default="{ row }">
              <el-tag :type="getPhaseTagType(row.phase)">
                {{ row.phase || 'info' }}
              </el-tag>
            </template>
          </el-table-column>
          <el-table-column label="步骤" width="200" prop="step" />
          <el-table-column label="消息" prop="message" />
        </el-table>
      </div>
    </div>

    <template #footer>
      <el-button @click="detailVisible = false">
        关闭
      </el-button>
    </template>
  </el-dialog>
</template>

<style scoped>
.monitor-page {
  width: 100%;       /* 占满可用宽度，响应式 */
  max-width: none;   /* 不限制最大宽度 */
  padding: 0 16px;   /* 两侧留白，避免贴边 */
  box-sizing: border-box;
}

.grid {
  display: grid;
  gap: 1.5rem;
}

.grid-cols-1 {
  grid-template-columns: repeat(1, minmax(0, 1fr));
}

@media (min-width: 1024px) {
  .lg\:grid-cols-2 {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* 更大屏幕下可进一步放宽左右留白 */
@media (min-width: 1600px) {
  .monitor-page { padding: 0 24px; }
}
</style>
